﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace NFinal.Sql.Like
{
    public class UTF8KeyUtil
    {
        public static byte[] GenerateKeys(int times = 5)
        {
            int[] keys = GenerateIntKeys(times);
            return Ints2Bytes(keys);
        }

        public static int[] GenerateIntKeys(int times=5)
        {
            int[] lens = new int[] { 93, 1920, 63488, 2031616, 65011711, 0x7FFFFFFF - 0x04000000 };
            int size = lens.Length;
            var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
            byte[] seedBuffer = new byte[4];
            int[] keys = new int[size * times + 1];
            keys[0] = times;
            for (int i = 0; i < lens.Length; i++)
            {
                rng.GetBytes(seedBuffer);
                int seed = BitConverter.ToInt32(seedBuffer, 0);
                var random = new Random(seed);
                for (int j = 0; j < times; j++)
                {
                    keys[i * times + j + 1] = random.Next(lens[i]);
                }
            }
            return keys;
        }

        private static byte[] Ints2Bytes(int[] ints)
        {
            byte[] bytes = new byte[ints.Length << 2];
            for (int i = 0; i < ints.Length; i++)
            {
                bytes[i << 2] = (byte)(ints[i] & 0xFF);
                bytes[(i << 2) + 1] = (byte)((ints[i] >> 8) & 0xFF);
                bytes[(i << 2) + 2] = (byte)((ints[i] >> 16) & 0xFF);
                bytes[(i << 2) + 3] = (byte)((ints[i] >> 24) & 0xFF);
            }
            return bytes;
        }
        private static int[] Bytes2Ints(byte[] bytes)
        {
            int[] ints = new int[bytes.Length >> 2];
            for (int i = 0; i < ints.Length; i++)
            {
                ints[i] = bytes[(i << 2)] | (bytes[(i << 2) + 1] << 8) | (bytes[(i << 2) + 2] << 16) | (bytes[(i << 2) + 3] << 24);
            }
            return ints;
        }

        public static int[] LoadIntKeyFromFile(string keyFilePath)
        {
            byte[] buffer = LoadKeyFromFile(keyFilePath);
            return Bytes2Ints(buffer);
        }

        public static byte[] LoadKeyFromFile(string keyFilePath)
        {
            string content = File.ReadAllText(keyFilePath);
            byte[] buffer = Convert.FromBase64String(content);
            return buffer;
        }

        public static void SaveIntKeyToFile(string keyFilePath, int[] keys)
        {
            byte[] buffer = Ints2Bytes(keys);
            SaveKeyToFile(keyFilePath, buffer);
        }

        public static void SaveKeyToFile(string keyFilePath,byte[] keys)
        {
            string content = Convert.ToBase64String(keys);
            File.WriteAllText(keyFilePath, content);
        }
    }
}
